package pl.kosmowska.ewelina.server.dao;

import java.lang.reflect.ParameterizedType;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.jdo.Transaction;

import pl.kosmowska.ewelina.server.PMF;
import pl.kosmowska.ewelina.server.jdo.DatabaseEntity;

import com.allen_sauer.gwt.log.client.Log;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

public class JdoDAOImpl<T> implements GenericDAO<DatabaseEntity<String>,String>{

	private static final Logger log = Logger.getLogger(JdoDAOImpl.class
			.getName());

	private Class<T> clazz;

	@SuppressWarnings("unchecked")
	public JdoDAOImpl() {
		this.clazz = ((Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0]);
	}

	public static PersistenceManager getPersistenceManager() {
		return PMF.get().getPersistenceManager();
	}

	public DatabaseEntity<String> findById(final String id) {
		if (id == null) {
			return null;
		}
		Key k = KeyFactory.stringToKey(id);
		PersistenceManager pm = getPersistenceManager();
		try {
			T e = pm.getObjectById(clazz, k);
			return (DatabaseEntity<String>) e;
		}catch (Exception e) {
			log.log(Level.SEVERE, "Error: JdoDAOImpl.findByKey(id)", e);
			log.severe(e.getMessage());
			Log.error(e.getMessage());
			return null;
		} finally {
			pm.close();
		}
	}
	
	public T findByKey(Key key) {
		if (key == null) {
			return null;
		}
		PersistenceManager pm = getPersistenceManager();
		try {
			T e = pm.getObjectById(clazz, key);
			return e;
		} catch (Exception e) {
			log.log(Level.SEVERE, "Error: JdoDAOImpl.findByKey(id): key=" + key, e);
			log.severe(e.getMessage());
			Log.error(e.getMessage());
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return null;
	}
	


	public DatabaseEntity<String> persistEntity(
			DatabaseEntity<String> entityData) {

		// set the owner of this entity
		Long uid = UserDataDAO.getLoggedInUserId();

		if (entityData.getVersion() == null) {
			entityData.setVersion(0l);
		}
		entityData.setVersion(entityData.getVersion() + 1);

		PersistenceManager pm = getPersistenceManager();
		Transaction tx = pm.currentTransaction();
		try {
			entityData.setUserId(uid);
			tx.begin();
			entityData = pm.makePersistent(entityData);
			tx.commit();

		} catch (Exception e) {
			log.log(Level.SEVERE, "Error: DataBaseEntity.persist(): this=" + this,
					e);
			//log.severe(e.getMessage());
		//	e.printStackTrace();
			Log.error( "Error: DataBaseEntity.persist(): this=");
			Log.error( "Error: DataBaseEntity.persist(): this=", e);
		} finally {
			if (tx.isActive()) {
				tx.rollback();
			}
			pm.close();
		}
		return entityData;
	}

	public Boolean deleteById(String id) {

		if (id == null) {
			return false;
		}
		Long uid = UserDataDAO.getLoggedInUserId();

		Key key = KeyFactory.stringToKey(id);

		Boolean success = false;
		PersistenceManager pm = getPersistenceManager();
		Transaction tx = pm.currentTransaction();
		try {

			T e = pm.getObjectById(clazz, key);
			tx.begin();
			pm.deletePersistent(e);
			tx.commit();
			success = true;

		} catch (Exception e) {
			log.log(Level.SEVERE, "Error: DataBaseEntity.deleteEntity(id): id="
					+ id, e);
			log.severe(e.getMessage());
			e.printStackTrace();
			Log.error(e.getMessage());
		} finally {
			if (tx.isActive()) {
				tx.rollback();
				success = false;
			}
			pm.close();
		}
		return success;
	}


}
